--[[
--Scripted by CobaltBW

--This is a recreation of Sonic's thok, made entirely through lua.
--The purpose of this script is to help teach newcomers the fundamentals of lua
--and ease the transition of learning its rules and syntax.

--Please make sure you are using an editor that can highlight code syntax, as this
--will make the tutorial (and code in general!) easier to read.

--]]

freeslot("sfx_airdsh", "SPR_DSHR", "MT_DASH_RING", "S_DASH_RING")

mobjinfo[MT_DASH_RING] = {
    doomednum = -1,
    spawnstate = S_DASH_RING,
    flags = MF_SCENERY|MF_NOCLIP|MF_NOGRAVITY
}
states[S_DASH_RING] = {
    sprite = SPR_DSHR,
    frame = A
}

addHook("MobjThinker", function(mo)
  local fusefade = {
    [0] = 0,
    [1] = FF_TRANS90,
    [2] = FF_TRANS80,
    [3] = FF_TRANS70,
    [4] = FF_TRANS60,
    [5] = FF_TRANS50,
    [6] = FF_TRANS40,
    [7] = FF_TRANS30,
    [8] = FF_TRANS20,
    [9] = FF_TRANS10
	}
  if mo and mo.valid
    if mo.fuse < 10
    and fusefade[mo.fuse/2]
      local fade = fusefade[mo.fuse/2]
      mo.frame = $|fade 
    end
  end
end,MT_DASH_RING)

sfxinfo[sfx_airdsh].caption = "Dash"
-- thokked stuff
addHook("PlayerThink", function(player)
local mo = player.mo -- Less hassle
if mo.skin == "jasonfox"
player.charability = CA_NONE
end
if not mo.hasthokked
	mo.hasthokked = false
	end
if (mo.eflags & MFE_JUSTHITFLOOR) or P_IsObjectOnGround(mo) or player.powers[pw_carry]
	mo.hasthokked = false
	end
end)

/*addHook("MobjCollide", function(player)
if player.mo.hasthokked == true*/


addHook("PlayerThink", function(player)
local mo = player.mo -- less hassle
mo.thoktime = $ or 0 --Just in case, if $ exists then use $ (current number), else use 0 (will be a number but wont work with "if mo.hammertime")
		if mo.thoktime
	mo.thoktime = $-1
		end
		
		if mo.hasthokked == false
	mo.thoktime = 9
		end
		
		if (player.mo.eflags & MFE_SPRUNG)
		or (player.pflags & PF_SHIELDABILITY)
		or P_PlayerInPain == true
		or player.playerstate != PST_LIVE
	mo.thoktime = 0
		end	
		
		if mo.hasthokked == true
		and not (player.cmd.buttons & BT_JUMP)
			mo.thoktime = 0
		end
	end)

--nograv moment ig?
addHook("PlayerThink", function(player)
	if player.mo.hasthokked == true
	and player.mo.thoktime > 0
	and P_IsObjectOnGround != true
	P_SetObjectMomZ(player.mo, 0, false)
	P_SpawnThokMobj(player)
	end
	end)

/*COM_AddCommand("ThokSound", function(p, var1)
    if gamestate != GS_LEVEL or not p.valid return end
    if var1 == "classic" then
        --classic code
    elseif var1 == "modern" then
        --modern code
    else
        CONS_Printf(p,"ThokSound is" $)
    end
end)*/
rawset(_G, "THKS", {})
rawset(_G, "THKM", {})
rawset(_G, "THKC", {})
rawset(_G, "THKR", {})

CV_RegisterVar{
	name = "LegacyThokSound", 
	defaultvalue = "Off", 
	flags = CV_NETVAR,
	PossibleValue = CV_OnOff
}

THKS.Global = CV_FindVar("LegacyThokSound")

CV_RegisterVar{
	name = "MomentumThokMode", 
	defaultvalue = "On", 
	flags = CV_NETVAR,
	PossibleValue = CV_OnOff
}

THKM.Global = CV_FindVar("MomentumThokMode")

CV_RegisterVar{
	name = "ColorChangeThok", 
	defaultvalue = "Off", 
	flags = CV_NETVAR,
	PossibleValue = CV_OnOff
}

THKC.Global = CV_FindVar("ColorChangeThok")

CV_RegisterVar{
	name = "RailgunThokMode", 
	defaultvalue = "Off", 
	flags = CV_NETVAR,
	PossibleValue = CV_OnOff
}

THKR.Global = CV_FindVar("RailgunThokMode")

addHook("PlayerThink", function(p)
	if THKS.Global.value and not THKS.active
		CONS_Printf(p, "Legacy Thok Sound is On.")
		--print("Legacy Thok Sound is On.")
		S_StartSound(p.mo, sfx_kc42)
		THKS.active = true
	
	elseif not THKS.Global.value and THKS.active
		CONS_Printf(p, "Legacy Thok Sound is Off.")
		--print("Legacy Thok Sound is Off.")
		S_StartSound(p.mo, sfx_kc34)
		THKS.active = false
	end
end)

addHook("PlayerThink", function(p)
	if THKM.Global.value and not THKM.active
		CONS_Printf(p, "Momentum Thok Mode is Enabled.")
		--print("Momentum Thok Mode is Enabled.")
		S_StartSound(p.mo, sfx_kc42)
		THKM.active = true
		
	elseif not THKM.Global.value and THKM.active
		CONS_Printf(p, "Momentum Thok Mode is Disabled.")
		--print("Momentum Thok Mode is Disabled.")
		S_StartSound(p.mo, sfx_kc34)
		THKM.active = false
	end
end)

addHook("PlayerThink", function(p)
	if THKC.Global.value and not THKC.active
		CONS_Printf(p, "Color Change Thok is Active.")
		--print("Color Change Thok is Active.")
		S_StartSound(p.mo, sfx_kc42)
		THKC.active = true
	
	elseif not THKC.Global.value and THKC.active
		CONS_Printf(p, "Color Change Thok is Inactive.")
		--print("Color Change Thok is Inactive.")
		S_StartSound(p.mo, sfx_kc34)
		THKC.active = false
	end
end)

addHook("PlayerThink", function(p)
	if THKR.Global.value and not THKR.active
		CONS_Printf(p, "Railgun Thok Mode is Enabled.")
		--print("Color Change Thok is Active.")
		S_StartSound(p.mo, sfx_kc42)
		THKR.active = true
	
	elseif not THKR.Global.value and THKR.active
		CONS_Printf(p, "Railgun Thok Mode is Disabled.")
		--print("Color Change Thok is Inactive.")
		S_StartSound(p.mo, sfx_kc34)
		THKR.active = false
	end
end)

--hopefully wall check

local function CheckAndCrumble(mo, sec)
  for fof in sec.ffloors()
    if not (fof.flags & FF_EXISTS) continue end -- Does it exist?
    if not (fof.flags & FF_BUSTUP) continue end -- Is it bustable?
    if (fof.flags & FF_STRONGBUST) then continue end --is it too tough for us?
    
    if mo.z + mo.height < fof.bottomheight continue end -- Are we too low?
    if mo.z > fof.topheight continue end -- Are we too high?

    -- Check for whatever else you may want to    

    EV_CrumbleChain(fof) -- Crumble
  end
end

addHook("PlayerThink", function(p)
  if not p.mo return end
  if p.mo.skin != "jasonfox" return end

    if p.mo.hasthokked == true and p.mo.thoktime > 0
      CheckAndCrumble(p.mo, p.mo.subsector.sector)
    end
end)

addHook("MobjLineCollide", function(mo, line)
  if not mo.player return end
  if mo.skin != "jasonfox" return end

  for _, sec in ipairs({line.frontsector, line.backsector})
    if mo.hasthokked == true and mo.thoktime > 0 then
      CheckAndCrumble(mo, sec)
    end
  end
end, MT_PLAYER)
	
--thok bounce check lmao
addHook("PlayerThink", function(player)
	if not (player.mo.eflags & MFE_VERTICALFLIP)
		and player.mo.momz > 0
			and player.mo.hasthokked == true
				and P_IsObjectOnGround != true
					and not (player.mo.eflags & MFE_GOOWATER)
		player.mo.hasthokked = false
	end
-- bounce check for shield abilities	
	if not (player.mo.eflags & MFE_VERTICALFLIP)
		and player.mo.momz > 0
	--goddamnit thundercoin im tired of you
			and not (player.powers[pw_shield] == SH_THUNDERCOIN)
				and (player.pflags & PF_THOKKED)
					and P_IsObjectOnGround != true
						and not (player.mo.eflags & MFE_GOOWATER)
							and player.mo.skin == "jasonfox"
		player.pflags = $&~PF_THOKKED
	end
--thok bounce check lmao REVERSE GRAVITY EDITION
	if (player.mo.eflags & MFE_VERTICALFLIP)
		and player.mo.momz < 0
			and player.mo.hasthokked == true
				and P_IsObjectOnGround != true
					and not (player.mo.eflags & MFE_GOOWATER)
		player.mo.hasthokked = false
	end
-- bounce check for shield abilities REVERSE GRAVITY EDITION	
	if (player.mo.eflags & MFE_VERTICALFLIP)
		and player.mo.momz < 0
	--goddamnit thundercoin im tired of you
			and not (player.powers[pw_shield] == SH_THUNDERCOIN)
				and (player.pflags & PF_THOKKED)
					and P_IsObjectOnGround != true
						and not (player.mo.eflags & MFE_GOOWATER)
							and player.mo.skin == "jasonfox"
		player.pflags = $&~PF_THOKKED
	end
end)

--force buff and also screw thundercoin	
	addHook("PlayerThink", function(player)
	if (player.powers[pw_shield] & ~SH_FORCEHP == SH_FORCE) and (player.pflags & PF_SHIELDABILITY)
	player.mo.hasthokked = false
	player.pflags = $|PF_THOKKED
	end
	
	if (player.powers[pw_shield] == SH_THUNDERCOIN)
	and (player.pflags & PF_THOKKED)
	player.mo.hasthokked = true
	end
	end)
	
/*
	addHook("PlayerThink", function(player)
	if player.mo.hasthokked == true
	and player.mo.thoktime >= 5
	and player.mo.state == S_PLAY_JUMP
	and P_IsObjectOnGround != true
	and not (player.pflags & PF_SHIELDABILITY)
	P_SetObjectMomZ(player.mo, 10*FRACUNIT, true)
	P_SpawnThokMobj(player)
	end
	
	if player.mo.hasthokked == true
	and player.mo.thoktime < 5 and player.mo.thoktime > 0
	and player.mo.state == S_PLAY_JUMP
	and P_IsObjectOnGround != true
	and not (player.pflags & PF_SHIELDABILITY)
	P_SetObjectMomZ(player.mo, -10*FRACUNIT, true)
	P_SpawnThokMobj(player)
	end
	
	if player.mo.thoktime < 1
	player.pflags = $ & ~PF_THOKKED
	end
end)*/
	
-- make srb2 not suck ass
addHook("PlayerThink", function(player)
if (player.pflags & PF_JUMPED) and (player.pflags & PF_SPINNING)
                player.pflags = $&~PF_SPINNING
        end
	end)

--[[
	Let's begin by creating a hook.
	
	Think of hooks as "events". Some hooks, like MobjThinker, PlayerThink,
	and ThinkFrame, run on every frame. Other hooks, like MobjSpawn, JumpSpecial,
	and MobjDamage, will only run on special conditions, like when the object is
	spawning, or when the player is trying to jump, or when an object is taking
	damage.
	
	A hook generally takes the format of: addHook("hook name", function, object)
	...where 'function' can refer to an existing function or can be created inline e.g.:
			function(arg1, arg2)
				<code block>
			end
		
	
	See this link for a list of hooks, the arguments they take, and information
	on when they're executed.
	https:--wiki.srb2.org/wiki/Lua/Hooks
	
	For this example, we need to modify the behavior of a player character that
	is trying to perform their midair ability. The "AbilitySpecial" hook is best
	equipped for this, since it takes place just before the ability is executed.
	In this case, AbilitySpecial's arg 2 function takes one argument, which is
	the player instance. It takes nothing for argument 3, so we won't include it.

	In effect, it will look like this:
			addHook("AbilitySpecial", function(player)
				<code block>
			end)
			
	Note: When calling function(), you can name these arguments anything you
	want; the important thing is that you know what those arguments represent
	when scripting the rest of your function. 
]]

addHook("AbilitySpecial", function(player)
	--First let's make sure we're using the right character skin.
	if player.mo.skin != "jasonfox"
		--CONS_Printf(player,"Skin is not sonic; exiting")
		return 
	end
	
	
	--Let's now check our player's flags to make sure we haven't thokked yet
	/*if player.pflags&PF_THOKKED*/ --This looks up player.pflags to see if the
	if player.mo.hasthokked == true
								--flag for PF_THOKKED is enabled.
		--CONS_Printf(player,"Sonic has already thokked; exiting")
		return true --Exit script. "True" in this case overrides the vanilla
	end
	
	local actionspd = FixedMul(player.mo.scale, player.actionspd)-- * 6/5
	if player.mo.eflags & MFE_UNDERWATER
	--	thokspd = $/2
		actionspd = $/2 -- We cut actionspd in half if travelling underwater.
	end
	if player.powers[pw_sneakers] or player.powers[pw_super]
	actionspd = $*3/2
	end
	
	if THKM.Global.value and THKM.active == true
	and not THKR.Global.value and THKR.active ~= true
		P_Thrust(player.mo, player.mo.angle, actionspd/2)
	end
	
	
	if not THKM.Global.value and THKM.active ~= true
	and not THKR.Global.value and THKR.active ~= true
		P_InstaThrust(player.mo, player.mo.angle, actionspd)
	end
	
	--if THKR.Global.value and THKR.active == true
		
	--end
	
	-- in the rare case
	if not THKM.Global.value and THKM.active ~= true
	and not THKR.Global.value and THKR.active ~= true
	and (FixedHypot(player.rmomx, player.rmomy) > actionspd)
		P_InstaThrust(player.mo, player.mo.angle, FixedHypot(player.rmomx, player.rmomy))
	end
	
	local mo = player.mo -- less hassle
	local dshr = P_SpawnMobjFromMobj(mo, -45*cos(player.drawangle + ANGLE_180), -45*sin(player.drawangle + ANGLE_180), FRACUNIT, MT_DASH_RING)
		dshr.scale = 1
		dshr.color = player.mo.color
		dshr.destscale = mo.scale * 2
		dshr.scalespeed = FRACUNIT/3
		dshr.fuse = 15
		dshr.state = S_DASH_RING
		--dshr.scale = ease.linear(3*FRACUNIT/10, dshr.scale, destscale)
		
			if dshr.fuse < 10
			local bop = byebye[dshr.fuse/2]
			dshr.frame = $|bop
			end
	
	local t = 10 - (dshr.fuse/2)
	dshr.frame = $ | (t << FF_TRANSSHIFT)

	local diff = FRACUNIT-mo.scale
local factor = 8
diff = $/factor
mo.scale = $+diff
	
	--Now we'll produce the sound effect at the player object's position.
	if THKS.Global.value and THKS.active == true
	and not THKR.Global.value and THKR.active ~= true
		S_StartSound(player.mo, sfx_airdsh)
	end

	if not THKS.Global.value and THKS.active ~= true
	and not THKR.Global.value and THKR.active ~= true
		S_StartSound(player.mo, sfx_thok)
		S_StartSound(player.mo, sfx_zoom)
		--S_StartSound(player.mo, sfx_spdpad)
	end
	
	if THKR.Global.value and THKR.active == true
		S_StartSound(player.mo, sfx_rail1)
	end
	
	-- Colorizer!
	if THKC.Global.value and THKC.active == true
		player.mo.color = P_RandomKey(#skincolors)
	end

	--Don't forget to set our "thokked" state, so the player can't spam it.
	/*player.pflags = $|PF_THOKKED*/ --The | operator turns on the PF_THOKKED flag
	player.mo.hasthokked = true
								--if it isn't already enabled.
	return true
end)